using System.Collections.Generic;
using UnityEngine;

namespace HybridCLR.Extension
{
    [System.Serializable]
    public class App
    {
        public string dllLoadPath = "Assets/HybridCLRGenerate/Dll/{0}";
        public string dllCallFun = "程序集.类名.静态方法名(无参)";
        IResources _resources;

        public IResources Resources
        {
            set => _resources = value;
            get => _resources;
        }
        
        public async System.Threading.Tasks.Task LoadAot()
        {
            var aotConfig = await _resources.LoadAssetAsync<TextAsset>(string.Format(dllLoadPath,"AotDllConfig.json"));
            AotDllConfig config = JsonUtility.FromJson<AotDllConfig>(aotConfig.text);
            _resources.Release(aotConfig);
            List<System.Threading.Tasks.Task<TextAsset>> tasks = new List<System.Threading.Tasks.Task<TextAsset>>();
            for (int i = 0; i < config.patchAot.Count; i++)
            {
                tasks.Add(_resources.LoadAssetAsync<TextAsset>(string.Format(dllLoadPath,$"{config.patchAot[i]}.dll.bytes")));
            }
            for (int i = 0; i < config.patchAot.Count; i++)
            {
                var thisDll = await tasks[i];
                HybridCLR.RuntimeApi.LoadMetadataForAOTAssembly(thisDll.bytes, HomologousImageMode.SuperSet);
                _resources.Release(thisDll);
            }
        }
        
        public async System.Threading.Tasks.Task LoadHot()
        {
            var hotConfig = await _resources.LoadAssetAsync<TextAsset>(string.Format(dllLoadPath,"HotDllConfig.json"));
            HotDllConfig config = JsonUtility.FromJson<HotDllConfig>(hotConfig.text);
            _resources.Release(hotConfig);
            List<System.Threading.Tasks.Task<TextAsset>> tasks1 = new List<System.Threading.Tasks.Task<TextAsset>>();
            List<System.Threading.Tasks.Task<TextAsset>> tasks2 = new List<System.Threading.Tasks.Task<TextAsset>>();
            for (int i = 0; i < config.hotUpdateAssemblyDefinitions.Count; i++)
            {
                tasks1.Add(_resources.LoadAssetAsync<TextAsset>(string.Format(dllLoadPath,$"{config.hotUpdateAssemblyDefinitions[i]}.dll.bytes")));
            }
            for (int i = 0; i < config.hotUpdateAssemblies.Count; i++)
            {
                tasks2.Add(_resources.LoadAssetAsync<TextAsset>(string.Format(dllLoadPath,$"{config.hotUpdateAssemblies[i]}.dll.bytes")));
            }
            for (int i = 0; i < config.hotUpdateAssemblyDefinitions.Count; i++)
            {
                var thisDll = await tasks1[i];
                // Editor环境下，HotUpdate.dll.bytes已经被自动加载，不需要加载，重复加载反而会出问题。
#if !UNITY_EDITOR
                System.Reflection.Assembly hotUpdateAss = System.Reflection.Assembly.Load(thisDll.bytes);
#endif
                _resources.Release(thisDll);
            }
            for (int i = 0; i < config.hotUpdateAssemblies.Count; i++)
            {
                var thisDll = await tasks1[i];
                // Editor环境下，HotUpdate.dll.bytes已经被自动加载，不需要加载，重复加载反而会出问题。
#if !UNITY_EDITOR
                System.Reflection.Assembly hotUpdateAss = System.Reflection.Assembly.Load(thisDll.bytes);
#endif
                _resources.Release(thisDll);
            }
        }

        public void CallFun()
        {
            var assemblies = System.AppDomain.CurrentDomain.GetAssemblies();
            string[] callAry = dllCallFun.Split('.');
            bool hasCall = false;
            if (callAry.Length >= 3)
            {
                foreach (var e in assemblies)
                {
                    if (e.GetName().Name == callAry[0])
                    {
                        System.Type type = e.GetType(callAry[1]);
                        type.GetMethod(callAry[2]).Invoke(null, null);
                        hasCall = true;
                    }
                }
            }

            if (!hasCall)
            {
                throw new System.Exception(dllCallFun + " Not found");
            }
        }
    }
}
